package com.ruyuan.rapid.core.context;

import io.netty.channel.ChannelHandlerContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * 基础上下文实现
 * @author mac
 */
public abstract class BasicContext implements Context {

    protected final String protocol;

    protected final ChannelHandlerContext nettyCtx;

    protected final boolean keepAlive;

    /**
     * 上下文的状态标识
     */
    protected volatile int status = Context.RUNNING;

    /**
     * 保存所有的上下文参数集合
     */
    protected final Map<AttributeKey<?>, Object> attributes = new HashMap<>();
    /**
     * 请求过程中的异常
     */
    protected Throwable throwable;

    /**
     * 定义是否已经释放请求资源
     */
    protected final AtomicBoolean requestReleased = new AtomicBoolean(false);
    /**
     * 存放回调函数的集合
     */
    protected List<Consumer<Context>> completedCallbacks;

    private long srTime;

    private long ssTime;

    private long rsTime;

    private long rrTime;

    public BasicContext(String protocol, ChannelHandlerContext nettyCtx, boolean keepAlive) {
        this.protocol = protocol;
        this.nettyCtx = nettyCtx;
        this.keepAlive = keepAlive;
    }

    /**
     * 设置上下文状态为正常运行状态
     */
    @Override
    public void runned() {
        status = Context.RUNNING;
    }

    /**
     * 设置上下文状态为标记写回状态
     */
    @Override
    public void writtened() {
        status = Context.WRITTEN;
    }

    /**
     * 设置上下文状态为写回结束
     */
    @Override
    public void completed() {
        status = Context.COMPLETED;
    }

    /**
     * 设置上下文状态为最终结束状态
     */
    @Override
    public void terminated() {
        status = Context.TERMINATED;
    }

    /**
     * 判断上下文状态是否正在运行
     * @return
     */
    @Override
    public boolean isRunning() {
        return status == Context.RUNNING;
    }

    /**
     * 判断是否标记写回响应状态
     * @return
     */
    @Override
    public boolean isWritten() {
        return status == Context.WRITTEN;
    }

    /**
     * 判断是否写回结束
     * @return
     */
    @Override
    public boolean isCompleted() {
        return status == Context.COMPLETED;
    }

    /**
     * 判断请求是否完全结束
     * @return
     */
    @Override
    public boolean isTerminated() {
        return status == Context.TERMINATED;
    }

    /**
     * 获取请求转换协议
     * @return
     */
    @Override
    public String getProtocol() {
        return this.protocol;
    }

    /**
     * 设置异常信息
     * @param throwable
     */
    @Override
    public void setThrowable(Throwable throwable) {
        this.throwable = throwable;
    }

    /**
     * 返回异常信息
     */
    @Override
    public Throwable getThrowable() {
        return throwable;
    }

    /**
     * 获取上下文参数
     * @param key 对应的key
     * @return
     */
    @Override
    public <T> T getAttribute(AttributeKey<T> key) {
        return (T) attributes.get(key);
    }

    /**
     * 设置上下文属性信息
     * @param key
     * @param value 上下文参数值
     * @return
     */
    @Override
    public <T> T putAttribute(AttributeKey<T> key, T value) {
        return (T) attributes.put(key, value);
    }

    /**
     * 获取netty上下文对象
     * @return
     */
    @Override
    public ChannelHandlerContext getNettyCtx() {
        return this.nettyCtx;
    }

    /**
     * 是否保持连接
     * @return
     */
    @Override
    public boolean isKeepAlive() {
        return this.keepAlive;
    }

    /**
     * 释放请求资源
     */
    @Override
    public void releaseRequest() {
        this.requestReleased.compareAndSet(false, true);
    }

    /**
     * 写回结束回调函数设置
     */
    @Override
    public void completedCallback(Consumer<Context> consumer) {
        if (completedCallbacks == null) {
            completedCallbacks = new ArrayList<>();
        }
        completedCallbacks.add(consumer);
    }

    /**
     * 回调函数执行
     */
    @Override
    public void invokeCompletedCallback() {
        if (completedCallbacks != null && completedCallbacks.size() > 0) {
            completedCallbacks.forEach(callback -> callback.accept(this));
        }
    }

    /**
     * SS 服务端发送请求时间
     * SR 服务端收到请求实现
     * RS 客户端发送请求时间
     * RR 客户单收到请求时间
     */
    @Override
    public long getSRTime() {
        return srTime;
    }

    @Override
    public void setSRTime(long srTime) {
        this.srTime = srTime;
    }

    @Override
    public long getSSTime() {
        return ssTime;
    }

    @Override
    public void setSSTime(long ssTime) {
        this.ssTime = ssTime;
    }

    @Override
    public long getRSTime() {
        return rsTime;
    }

    @Override
    public void setRSTime(long rsTime) {
        this.rsTime = rsTime;
    }

    @Override
    public long getRRTime() {
        return rrTime;
    }

    @Override
    public void setRRTime(long rrTime) {

    }
}
